﻿// -----------------------------------------------------------------------
// <copyright file="TrainerService.cs" company="AGR">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace AGR.Services.Employee.Contract
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using AGR.Data.Repository;
    using AGR.Model;
    using AGR.Data.Repository.Contract;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class TrainerService : ITrainerService
    {
        private ContextHelper _contextHelper;

        private IRepository<Employee> _employeeRepository;
        private IRepository<Course> _courseRepository;
        private IRepository<Subject> _subjectRepository;
        private IRepository<FactCourseSubjectTrainer> _factCourseSubjectTrainerRepository;
        
        public TrainerService()
        {
            _contextHelper = ContextHelper.GetInstance();

            _employeeRepository = new EmployeeRepository(_contextHelper);
            _courseRepository = new CourseRepository(_contextHelper);
            _subjectRepository = new SubjectRepository(_contextHelper);
            _factCourseSubjectTrainerRepository = new FactCourseSubjectTrainerRepository(_contextHelper);
        }

        #region Private Methods

        private static void ActionResultError(ActionResult actionResult, Exception ex)
        {
            actionResult.Exception = ex;
            actionResult.IsSystemFailure = true;
            actionResult.Success = false;
        }

        #endregion

        public ActionResult AddSubjectToLecture(string employeeCode, string courseCode, string subjectCode, string userCreated)
        {
            if (string.IsNullOrEmpty(employeeCode))
                throw new ArgumentNullException(employeeCode);
            if (string.IsNullOrEmpty(courseCode))
                throw new ArgumentNullException(courseCode);
            if (string.IsNullOrEmpty(subjectCode))
                throw new ArgumentNullException(subjectCode);
            if (string.IsNullOrEmpty(userCreated))
                throw new ArgumentNullException(userCreated);

            var exists = _factCourseSubjectTrainerRepository.FindSingleBy(x => x.CourseCode == courseCode &&
                                                                               x.SubjectCode == subjectCode);

            var actionResult = new ActionResult();

            try
            {
                if (exists == null)
                {
                    var entity = new FactCourseSubjectTrainer()
                    {
                        CourseCode = courseCode,
                        SubjectCode = subjectCode,
                        EmployeeCode = employeeCode,
                        UserCreated = userCreated
                    };
                    _factCourseSubjectTrainerRepository.Add(entity);
                }
                else
                {
                    exists.EmployeeCode = employeeCode;
                    _factCourseSubjectTrainerRepository.Update(exists);
                }

                _factCourseSubjectTrainerRepository.SaveChanges();

                actionResult.Success = true;
                actionResult.Message = actionResult.RecordInserted;
            }
            catch (Exception ex)
            {
                ActionResultError(actionResult, ex);
                actionResult.Message = actionResult.GenericAddErrorMessage;
            }

            return actionResult;
        }

        public ActionResult DeleteTrainerFromLecture(string employeeCode, string courseCode, string subjectCode, string userModified)
        {
            if (string.IsNullOrEmpty(employeeCode))
                throw new ArgumentNullException(employeeCode);
            if (string.IsNullOrEmpty(courseCode))
                throw new ArgumentNullException(courseCode);
            if (string.IsNullOrEmpty(subjectCode))
                throw new ArgumentNullException(subjectCode);
            if (string.IsNullOrEmpty(userModified))
                throw new ArgumentNullException(userModified);

            var exists = _factCourseSubjectTrainerRepository.FindSingleBy(x => x.CourseCode == courseCode &&
                                                                               x.SubjectCode == subjectCode &&
                                                                               x.EmployeeCode == employeeCode);

            var actionResult = new ActionResult();

            try
            {
                exists.EmployeeCode = null;
                exists.UserModified = userModified;
                _factCourseSubjectTrainerRepository.Update(exists);
                _factCourseSubjectTrainerRepository.SaveChanges();

                actionResult.Success = true;
                actionResult.Message = actionResult.RecordDeleted;
            }
            catch (Exception ex)
            {
                ActionResultError(actionResult, ex);
                actionResult.Message = actionResult.GenericAddErrorMessage;
            }

            return actionResult;
        }

        public IList<Course> GetTrainerCoursesLectured(string employeeCode)
        {
            if (string.IsNullOrEmpty(employeeCode))
                throw new ArgumentNullException(employeeCode);

            var courseSubjects = _factCourseSubjectTrainerRepository.FindByReadOnly(x => x.EmployeeCode == employeeCode);

            IList<Course> courses = null;

            if (courseSubjects.Count > 0)
            {
                courses = new List<Course>();

                foreach (var courseSubject in courseSubjects)
                    courses.Add(_courseRepository.FindSingleBy(x => x.CourseCode == courseSubject.CourseCode));
            }

            return courses;
        }

        public IList<Subject> GetTrainerSubjectsLectured(string employeeCode)
        {
            if (string.IsNullOrEmpty(employeeCode))
                throw new ArgumentNullException(employeeCode);

            var courseSubjects = _factCourseSubjectTrainerRepository.FindByReadOnly(x => x.EmployeeCode == employeeCode);

            IList<Subject> subjects = null;

            if (courseSubjects.Count > 0)
            {
                subjects = new List<Subject>();

                foreach (var courseSubject in courseSubjects)
                    subjects.Add(_subjectRepository.FindSingleBy(x => x.SubjectCode == courseSubject.SubjectCode));
            }

            return subjects;
        }

        public IList<FactCourseSubjectTrainer> GetLectures(string employeeCode)
        {
            if (string.IsNullOrEmpty(employeeCode))
                throw new ArgumentNullException(employeeCode);

            return _factCourseSubjectTrainerRepository.FindBy(x => x.EmployeeCode == employeeCode).ToList();
        }

        public FactCourseSubjectTrainer GetLecture(string courseCode, string subjectCode)
        {
            if (string.IsNullOrEmpty(courseCode))
                throw new ArgumentNullException(courseCode);

            if (string.IsNullOrEmpty(subjectCode))
                throw new ArgumentNullException(subjectCode);

            return _factCourseSubjectTrainerRepository.FindSingleBy(x => x.CourseCode == courseCode && x.SubjectCode == subjectCode);
        }

        public IList<Employee> GetTrainersThatLectureCourse(string courseCode)
        {
            if (string.IsNullOrEmpty(courseCode))
                throw new ArgumentNullException(courseCode);

            var courseTrainers = _factCourseSubjectTrainerRepository.FindByReadOnly(x => x.CourseCode == courseCode);

            ISet<Employee> trainers = null;

            if (courseTrainers.Count > 0)
            {
                trainers = new HashSet<Employee>();

                foreach (var courseTrainer in courseTrainers)
                    trainers.Add(_employeeRepository.FindSingleBy(x => x.EmployeeCode == courseTrainer.EmployeeCode));
            }

            return trainers.ToList();
        }

        public IList<Employee> GetTrainersThatLectureSubject(string subjectCode)
        {
            if (string.IsNullOrEmpty(subjectCode))
                throw new ArgumentNullException(subjectCode);

            var subjectTrainers = _factCourseSubjectTrainerRepository.FindByReadOnly(x => x.SubjectCode == subjectCode);

            ISet<Employee> trainers = null;

            if (subjectTrainers.Count > 0)
            {
                trainers = new HashSet<Employee>();

                foreach (var subjectTrainer in subjectTrainers)
                    trainers.Add(_employeeRepository.FindSingleBy(x => x.EmployeeCode == subjectTrainer.EmployeeCode));
            }

            return trainers.ToList();
        }

        #region Dispose

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (_contextHelper != null)
                        _contextHelper.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
